package com.wxpay.demo.controller;


import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.google.common.collect.Maps;
import com.wxpay.demo.constant.WXPayConstants;
import com.wxpay.demo.model.PreOrderRequest;
import com.wxpay.demo.properteis.WxProperties;
import com.wxpay.demo.utils.IpAddr;
import com.wxpay.demo.utils.WXPayUtil;
import com.wxpay.demo.utils.WxResultUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;


/**
 * 【微信接口示例】
 * 控制器
 * @date 2021-06-15
 * @author  yls
 */
@RestController
@RequestMapping("/wx")
@Slf4j
public class WxController {


    @Autowired
    private WxProperties wxProperties;

    @Autowired
    private WxPayService wxPayService;




    /**
     * 支付回调，统一下单配置回调地址
     * 此函数会被执行多次，如果支付状态已经修改为已支付，则下次再调的时候判断是否已经支付，如果已经支付了，则什么也执行
     * @param request
     * @param response
     * @return
     * @throws IOException
     * @throws
     */
    @RequestMapping(value = "notifyWXPay", produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public String notifyWXPay(HttpServletRequest request, HttpServletResponse response) {
        String responseXml;
        try {
            log.info("------------------------微信支付回调start-------------------->>>");
            InputStream inStream = request.getInputStream();
            ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            String resultxml = new String(outSteam.toByteArray(), "utf-8");

            outSteam.close();
            inStream.close();

            final WxPayOrderNotifyResult notifyResult = this.wxPayService.parseOrderNotifyResult(resultxml);
            log.info("#WxController.notifyWXPay# WxPayOrderNotifyResult result is :{}", notifyResult);

            if(WxPayConstants.ResultCode.SUCCESS.equalsIgnoreCase(notifyResult.getResultCode())) {
                // 验证通过才能记到流水表中，否则不计入
                if (WXPayUtil.isSignatureValid(resultxml, wxProperties.getMchKey())) {
                    // 签名正确
                    // 进行处理。
                    // 注意特殊情况：订单已经退款，但收到了支付结果成功的通知，不应把商户侧订单状态从退款改成支付成功
                    log.info("===============验签成功，付款成功==============");
                    // TODO 可以通过订单Id修改订单状态,根据自己业务场景处理

                    responseXml=WxResultUtil.returnXML(WXPayConstants.SUCCESS,"验签成功，付款成功");

                } else {
                    //验签失败
                    // 签名错误，如果数据里没有sign字段，也认为是签名错误
                    log.info("===============验签失败==============");
                    responseXml=WxResultUtil.returnXML(WXPayConstants.FAIL,"验签失败");
                }
            }else{
                log.info("-----------------支付返回code失败-------------------------"+notifyResult.getResultCode());
                log.info("-----------------result xml is :{}-------------------------",resultxml);
                responseXml=WxResultUtil.returnXML(WXPayConstants.FAIL,"支付返回失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            responseXml=WxResultUtil.returnXML(WXPayConstants.FAIL,e.getMessage());
        }
        log.info("------------------------微信支付回调end-------------------->>>");
        return responseXml;
     }




    /**
     * 退款回调，申请退款配置回调地址
     * @param request
     * @param response
     * @return
     * @throws IOException
     * @throws
     */
    @RequestMapping(value = "notifyWXRefund", produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public String notifyWXRefund(HttpServletRequest request, HttpServletResponse response){
        String responseXml;
        try {
            System.out.println("微信退款回调");
            InputStream inStream = request.getInputStream();
            ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            String resultxml = new String(outSteam.toByteArray(), "utf-8");

            outSteam.close();
            inStream.close();

            final WxPayRefundNotifyResult result = this.wxPayService.parseRefundNotifyResult(resultxml);
            log.info("#WxController.notifyWXRefund# WxPayRefundNotifyResult result is :{}", result);

            log.info("-----------------微信退款回调result.getResultCode()-------------------------"+result.getReturnCode());

            if(WxPayConstants.ResultCode.SUCCESS.equalsIgnoreCase(result.getReturnCode())) {
                WxPayRefundNotifyResult.ReqInfo reqInfo= result.getReqInfo();
                log.info("-----------------微信退款回调ReqInfo:{}-------------------------",reqInfo);

                if(reqInfo.getRefundStatus().equals(WXPayConstants.SUCCESS)){
                    log.info("--------------------------退款成功---------------------");
                    //退款成功
                    responseXml=WxResultUtil.returnXML(WXPayConstants.SUCCESS,"退款成功");
                }else{
                    log.info("--------------------------退款失败---------------------");
                    //异步确认，8次以后就认为失败了
                    responseXml=WxResultUtil.returnXML(WXPayConstants.FAIL,"退款失败");
                }

            }else{
                log.info("-----------------result xml is :{}-------------------------",resultxml);
                responseXml=WxResultUtil.returnXML(WXPayConstants.FAIL,"resultCode is"+result.getResultCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
            responseXml=WxResultUtil.returnXML(WXPayConstants.FAIL,e.getMessage());
        }
        return responseXml;
    }

}
